package com.zenjava.update.ui;

import com.zenjava.update.AppProfile;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Parent;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.HBox;
import javafx.stage.Popup;

import java.util.logging.Level;
import java.util.logging.Logger;

public class CurrentVersionBar extends HBox
{
    private final static Logger LOGGER = Logger.getLogger(CurrentVersionBar.class.getName());
    
    private ProgressIndicator progressIndicator;
    private Label currentVersionLabel;
    private Hyperlink showDetailsLink;
    private Popup detailsPopup;
    private AppProfileView detailsView;
    private LoadInstalledAppProfileService loadInstalledAppProfileService;
    
    public CurrentVersionBar()
    {
        buildView();
    }
    
    public void load()
    {
        loadInstalledAppProfileService.restart();
    }
    
    protected void showDetails()
    {
        if (detailsPopup == null)
        {
            detailsPopup = new Popup();
            detailsView = new AppProfileView();
            detailsView.getStyleClass().add("current-version-details-view");
            detailsPopup.setAutoHide(true);
            detailsPopup.setAutoFix(true);
            detailsPopup.getContent().add(detailsView);
        }
        detailsView.setAppProfile(loadInstalledAppProfileService.getValue());

        Parent parent = showDetailsLink.getParent();
        Bounds childBounds = showDetailsLink.getBoundsInParent();
        Bounds parentBounds = parent.localToScene(parent.getBoundsInLocal());
        double layoutX = childBounds.getMinX()
                + parentBounds.getMinX() + parent.getScene().getX() + parent.getScene().getWindow().getX();
        double layoutY = childBounds.getMaxY()
                + parentBounds.getMinY() + parent.getScene().getY() + parent.getScene().getWindow().getY();
        detailsPopup.show(showDetailsLink, layoutX, layoutY);
    }
    
    private void buildView()
    {
        setSpacing(10);
        getStyleClass().add("current-version-bar");

        progressIndicator = new ProgressIndicator();
        getChildren().add(progressIndicator);
        
        currentVersionLabel = new Label();
        getChildren().add(currentVersionLabel);
        
        showDetailsLink = new Hyperlink("(details)");
        showDetailsLink.setVisible(false);
        showDetailsLink.setOnAction(new EventHandler<ActionEvent>() 
        {
            public void handle(ActionEvent event)
            {
                showDetails();
            }
        });
        getChildren().add(showDetailsLink);
        
        loadInstalledAppProfileService = new LoadInstalledAppProfileService();

        progressIndicator.prefHeightProperty().bind(currentVersionLabel.heightProperty());
        progressIndicator.maxWidthProperty().bind(progressIndicator.heightProperty());
        progressIndicator.visibleProperty().bind(loadInstalledAppProfileService.runningProperty());
        
        progressIndicator.visibleProperty().addListener(new ChangeListener<Boolean>() 
        {
            public void changed(ObservableValue<? extends Boolean> source, Boolean wasRunning, Boolean isRunning)
            {
                if (isRunning)
                {
                    currentVersionLabel.setText("loading...");
                }
            }
        });

        showDetailsLink.visibleProperty().bind(loadInstalledAppProfileService.valueProperty().isNotNull());

        loadInstalledAppProfileService.setOnSucceeded(new EventHandler<WorkerStateEvent>()
        {
            public void handle(WorkerStateEvent event)
            {
                AppProfile value = loadInstalledAppProfileService.getValue();
                currentVersionLabel.setText(String.format("%s (version %s)", value.getName(), value.getVersion()));
            }
        });
        
        loadInstalledAppProfileService.setOnFailed(new EventHandler<WorkerStateEvent>()
        {
            public void handle(WorkerStateEvent event)
            {
                LOGGER.log(Level.WARNING, "Unable to load current version details", loadInstalledAppProfileService.getException());
                currentVersionLabel.setText("Unable to determine current version");
            }
        });
    }
}
